package com.huajx.core.kit;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.huajx.util.CharsetUtil;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.concurrent.FutureCallback;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClients;
import org.apache.http.impl.nio.reactor.IOReactorConfig;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.huajx.util.StrUtil;
import com.huajx.util.convert.Convert;

/**
 * 异步Http请求工具类
 *
 */
public class AsyncHttpClientKit {
    private final static Logger logger = LoggerFactory.getLogger(AsyncHttpClientKit.class);
    private static CloseableHttpAsyncClient httpClient;
    private static volatile boolean isClientStart;

    private static CloseableHttpAsyncClient createCustomAsyncClient() {
        if(isClientStart){
            logger.info("客户端HttpAsyncClient已经建立过了");
            return httpClient;
        }
//		Preconditions.checkState(!isClientStart, "客户端HttpAsyncClient已经建立过了");
        IOReactorConfig ioReactorConfig = IOReactorConfig.custom()
                .setIoThreadCount(Runtime.getRuntime().availableProcessors()).setConnectTimeout(60000)
                .setSoTimeout(60000).build(); // 设置超时时间 毫秒为单位
        RequestConfig requestConfig = RequestConfig.copy(RequestConfig.DEFAULT).setConnectTimeout(60000).build();
        return HttpAsyncClients.custom().setDefaultIOReactorConfig(ioReactorConfig)
                .setDefaultRequestConfig(requestConfig).build();
    }

    public static void startHttpClient() {
        httpClient = createCustomAsyncClient();
        httpClient.start();
        isClientStart = true;
    }

    public static void closeHttpClient() {
        try {
            httpClient.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        isClientStart = false;
    }

    public static void http(String method, String url, Object parameter, StringFutureCallback callback) {
        if(method == null){
            logger.info("method不能为空");
            return;
        }
//		Preconditions.checkNotNull(method);
        if ("GET".equals(method)) {
            get(url, callback);
        } else if ("POST".equals(method)) {
            post(url, parameter, callback);
        }
    }

    public static void get(String url, StringFutureCallback callback) {
        if(!isClientStart){
            logger.info("还没有建立Http Client");
            startHttpClient();
        }
//		Preconditions.checkArgument(isClientStart, "还没有建立Http Client");
        HttpUriRequest request = new HttpGet(url);
        httpClient.execute(request, new DefaultFutureCallback(callback));
    }

    @SuppressWarnings("unchecked")
    public static void post(String url, Object parameter, StringFutureCallback callback) {
        if(!isClientStart){
            logger.info("还没有建立Http Client");
            startHttpClient();
        }
//		Preconditions.checkArgument(isClientStart, "还没有建立Http Client");
        HttpPost httpPost = new HttpPost(url);
        if (parameter != null) {
            List<BasicNameValuePair> pairs = new ArrayList<>();//Lists.newArrayList();
            UrlEncodedFormEntity entity = null;
            if (parameter instanceof HashMap) {
                Map<String, Object> parameters = (Map<String, Object>) parameter;
                parameters.forEach((k, v) -> pairs.add(new BasicNameValuePair(k, Convert.toStr(v, StrUtil.EMPTY))));
                entity = new UrlEncodedFormEntity(pairs, CharsetUtil.CHARSET_UTF_8);
            }else if(parameter instanceof String){
//					Map<String, String> parameters = new Has(Map<String, String>) parameter;
                pairs.add(new BasicNameValuePair("content", (String)parameter));
                entity = new UrlEncodedFormEntity(pairs, CharsetUtil.CHARSET_UTF_8);
            }
            httpPost.setEntity(entity);
        }
        httpClient.execute(httpPost, new DefaultFutureCallback(callback));
    }

    /** * 字符串类型结果回调 */
    public interface StringFutureCallback {
        void success(String content);
    }

    public static class DefaultFutureCallback implements FutureCallback<HttpResponse> {
        private StringFutureCallback callback;

        public DefaultFutureCallback(StringFutureCallback callback) {
            this.callback = callback;
        }

        @Override
        public void completed(HttpResponse httpResponse) {
            HttpEntity entity = httpResponse.getEntity();
            String content = "";
            try {
                content = EntityUtils.toString(entity, CharsetUtil.CHARSET_UTF_8);
            } catch (IOException e) {
                e.printStackTrace();
            }
            callback.success(content);
        }

        @Override
        public void failed(Exception e) {
            e.printStackTrace();
        }

        @Override
        public void cancelled() {
//			logger.debug("core request cancelled");
        }

    }
}
